package jmine.tec.script.impl;

import jmine.tec.script.ScriptDispatcher;
import jmine.tec.script.ScriptExecutionContext;
import jmine.tec.script.ScriptExecutor;
import jmine.tec.script.ScriptExecutorException;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * @author jrenaut
 */
public class ASimpleScriptDispatcherShould {

    private ScriptDispatcher sd = null;

    private MockExecutor calledExecutor = null;

    private MockExecutor uncalledExecutor = null;

    @Before
    public void before() {
        this.sd = new SimpleScriptDispatcher();
        this.calledExecutor = new MockExecutor();
        this.uncalledExecutor = new MockExecutor();
        this.sd.setScriptExecutors(this.calledExecutor, this.uncalledExecutor);
    }

    @Test
    public void callOnlyFirstExecutor() throws ScriptExecutorException {

        Assert.assertFalse(this.calledExecutor.execution);
        Assert.assertFalse(this.calledExecutor.validations);
        Assert.assertFalse(this.calledExecutor.dependencies);
        Assert.assertFalse(this.uncalledExecutor.execution);
        Assert.assertFalse(this.uncalledExecutor.validations);
        Assert.assertFalse(this.uncalledExecutor.dependencies);

        this.sd.dispatchExecution(null);

        Assert.assertTrue(this.calledExecutor.execution);
        Assert.assertFalse(this.calledExecutor.validations);
        Assert.assertFalse(this.calledExecutor.dependencies);
        Assert.assertFalse(this.uncalledExecutor.execution);
        Assert.assertFalse(this.uncalledExecutor.validations);
        Assert.assertFalse(this.uncalledExecutor.dependencies);

        this.sd.dispatchGetValidations(null);

        Assert.assertTrue(this.calledExecutor.execution);
        Assert.assertTrue(this.calledExecutor.validations);
        Assert.assertFalse(this.calledExecutor.dependencies);
        Assert.assertFalse(this.uncalledExecutor.execution);
        Assert.assertFalse(this.uncalledExecutor.validations);
        Assert.assertFalse(this.uncalledExecutor.dependencies);

        this.sd.dispatchGetDependencies(null);

        Assert.assertTrue(this.calledExecutor.execution);
        Assert.assertTrue(this.calledExecutor.validations);
        Assert.assertTrue(this.calledExecutor.dependencies);
        Assert.assertFalse(this.uncalledExecutor.execution);
        Assert.assertFalse(this.uncalledExecutor.validations);
        Assert.assertFalse(this.uncalledExecutor.dependencies);
    }

    private final class MockExecutor implements ScriptExecutor {

        private boolean execution = false;

        private boolean dependencies = false;

        private boolean validations = false;

        /**
         * {@inheritDoc}
         */
        public <R> R execute(ScriptExecutionContext<R> context) throws ScriptExecutorException {
            this.execution = true;
            return null;
        }

        /**
         * {@inheritDoc}
         */
        public <R> R getDependencies(ScriptExecutionContext<R> context) throws ScriptExecutorException {
            this.dependencies = true;
            return null;
        }

        /**
         * {@inheritDoc}
         */
        public <R> R getValidations(ScriptExecutionContext<R> context) throws ScriptExecutorException {
            this.validations = true;
            return null;
        }

    }
}
